﻿using System.Runtime.InteropServices;
using System.Runtime.Serialization;

namespace Authorization
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Interop.Security.AzRoles;    
    
    [DataContract(Name = "RoleAssignment", Namespace = "http://authorizationservices/v1")]
    public class RoleAssignment
    {
        private readonly IAzRoleAssignment azRoleAssignment;

        #region Properties

        public Application Application { get; internal set; }

        [DataMember(Name = "Description", IsRequired = false)]
        public string Description { get; set; }

        [DataMember(Name = "Name", IsRequired = true)]
        public string Name { get; set; }

        [DataMember(Name = "ScopeName", IsRequired = false)]
        public string ScopeName
        {
            get  { return this.Scope != null ? this.Scope.Name : null; }
            internal set {}
        }

        [DataMember(Name = "RoleDefinitionNames", IsRequired = true)]
        public string[] RoleDefinitionNames
        {
            get { return GetRoleDefinitionNames(); }
            internal set{}
        }

        //[DataMember(Name = "TaskNames", IsRequired = true)]
        //public string[] TaskNames
        //{
        //    get { return GetTaskNames(); }
        //    internal set { }
        //}

        //[DataMember(Name = "OperationNames", IsRequired = true)]
        //public string[] OperationNames
        //{
        //    get;
        //    internal set;
        //}

        //[DataMember(Name = "RoleNames", IsRequired = true)]
        //public string[] RoleNames
        //{
        //    get;
        //    internal set;
        //}

        //[DataMember(Name = "MemberNames", IsRequired = true)]
        //public string[] MemberNames
        //{
        //    get
        //    {
        //     return    getmem
        //    } 
        //    internal set;
        //}

        public Scope Scope { get; internal set; }
        public Definition Definition { get; internal set; }

        #endregion

        internal RoleAssignment(Application application, IAzRoleAssignment azmanRoleAssignment)
        {
            this.Application = application;
            this.Description = azmanRoleAssignment.Description;
            this.Name = azmanRoleAssignment.Name;
            this.azRoleAssignment = azmanRoleAssignment;

            if (azmanRoleAssignment.Scope != null)
            {
                this.Scope = new Scope(application, azmanRoleAssignment.Scope as IAzScope2);
                this.Definition = Definition.Scope;                
            }
            else
            {
                this.Definition = Definition.Application;
            }
        }

        public void AddApplicationGroupMember(string applicationGroupName)
        {
            SecUtility.CheckParameter(ref applicationGroupName, true, true, false, 64, "applicationGroupName");
            this.azRoleAssignment.AddAppMember(applicationGroupName, null);
        }

        public void AddMember(string Sid)
        {
            SecUtility.CheckParameter(ref Sid, true, true, false, 64, "SID");
            this.azRoleAssignment.AddMember(Sid, null);
        }

        public void AddMemberName(string memberName)
        {
            SecUtility.CheckParameter(ref memberName, true, true, false, 64, "memberName");
            this.azRoleAssignment.AddMember(memberName, null);
        }        
    
        public void DeleteMemberNames(string[] usernames)
        {
            SecUtility.CheckArrayParameter(ref usernames, true, true, false, 64, "usernames");
            foreach (var username in usernames)
            {
                this.azRoleAssignment.DeleteMemberName(username,null);
            }
        }
       
        public void DeleteMembers(string[] SID)
        {
            SecUtility.CheckArrayParameter(ref SID, true, true, false, 64, "SID");
            foreach (var username in SID)
            {
                this.azRoleAssignment.DeleteMember(username, null);
            }
        }

        public void AddMembers(string[] Sids)
        {
            SecUtility.CheckArrayParameter(ref Sids, true, true, false, 64, "SIDs");
            foreach (var Sid in Sids)
            {
                this.azRoleAssignment.AddMember(Sid, null);
            }
        }

        public void DeleteApplicationGroupMember(string[] applicationGroupNames)
        {
            SecUtility.CheckArrayParameter(ref applicationGroupNames, true, true, false, 64, "applicationGroupNames");
            foreach (var username in applicationGroupNames)
            {
                this.azRoleAssignment.DeleteAppMember(username, null);
            }
        }

        public void AddMemberNames(string[] memberNames)
        {
            SecUtility.CheckArrayParameter (ref memberNames, true, true, false, 64, "memberNames");
            foreach (var memberName in memberNames)
            {
                this.azRoleAssignment.AddMemberName(memberName, null);
            }
        }
         
        public void AddOperation(string operationName)
        {
            SecUtility.CheckParameter(ref operationName, true, true, false, 64, "memberName");
            this.azRoleAssignment.AddOperation(operationName, null);
        }

        public void AddRoleDefinition(string roleDefinitionName)
        {
            SecUtility.CheckParameter(ref roleDefinitionName, true, true, false, 64, "roleDefinitionName");
            this.azRoleAssignment.AddRoleDefinition(roleDefinitionName);
        }

        public void AddTask(string taskName)
        {
            SecUtility.CheckParameter(ref taskName, true, true, false, 64, "taskName");
            this.azRoleAssignment.AddTask(taskName, null);
        }

        public void DeleteApplicationGroupMember(string applicationGroupName)
        {
            SecUtility.CheckParameter(ref applicationGroupName, true, true, false, 64, "applicationGroupName");
            this.azRoleAssignment.DeleteAppMember(applicationGroupName, null);
        }
        
        public void DeleteMember(string Sid)
        {
            SecUtility.CheckParameter(ref Sid, true, true, false, 64, "SID");
            this.azRoleAssignment.DeleteMemberName(Sid, null);
        }

        public void DeleteMemberName(string memberName)
        {
            SecUtility.CheckParameter(ref memberName, true, true, false, 64, "memberName");
            this.azRoleAssignment.DeleteMemberName(memberName, null);
        }

        public void DeleteOperation(string operationName)
        {
            SecUtility.CheckParameter(ref operationName, true, true, false, 64, "memberName");
            this.azRoleAssignment.DeleteOperation(operationName, null);
        }

        public void DeleteRoleDefinition(string roleDefinitionName)
        {
            SecUtility.CheckParameter(ref roleDefinitionName, true, true, false, 64, "roleDefinitionName");
            this.azRoleAssignment.DeleteRoleDefinition(roleDefinitionName);
        }

        public void  DeleteTask(string taskName)
        {
            SecUtility.CheckParameter(ref taskName, true, true, false, 64, "taskName");
            this.azRoleAssignment.DeleteTask(taskName, null);
        }

        public string[] GetApplicationGroupMemberNames()
        {
            return this.azRoleAssignment.AppMembers as string[];
        }

        public ApplicationGroupCollection GetApplicationGroupMembers()
        {
            var appMembers = (string[]) this.azRoleAssignment.AppMembers;

            var appGroups = new ApplicationGroupCollection();
            var scopeName = this.Scope != null ? this.Scope.Name : null;

            if (appMembers!=null)
            {
                foreach (var appMember in appMembers)
                {
                    appGroups.Add(this.Application.GetApplicationGroup(appMember, scopeName));
                }
            }

            return appGroups;
        }

        public string[] GetMembers()
        {
            return Util.ObjectToArrayOfString(this.azRoleAssignment.Members);
        }

        public string[] GetMembersName()
        {
            return Util.ObjectToArrayOfString(this.azRoleAssignment.MembersName);
        }

        public string[] GetOperationNames()
        {
            return Util.ObjectToArrayOfString(this.azRoleAssignment.Operations);
        }

        public OperationCollection GetOperations()
        {
            var ops = new OperationCollection();
            foreach (var op in GetOperationNames())
            {
                ops.Add(this.Application.GetOperation(op) );
            }
            return ops;
        }

        public RoleDefinitionCollection GetRoleDefinitions()
        {
            return new RoleDefinitionCollection(this.Application, this.azRoleAssignment.RoleDefinitions, this.Scope.Name);
        }

        public string[] GetRoleDefinitionNames()
        {
            var result = new List<string>();
             foreach (IAzRoleDefinition role in this.azRoleAssignment.RoleDefinitions)
            {
                result.Add(Name);
            }

            return result.ToArray();
        }

        public TaskCollection GetTasks()
        {
            string scopeName = this.Scope != null ? this.Scope.Name : null;

            var tasks = new TaskCollection();
            foreach (var task in GetTaskNames())
            {
                tasks.Add(Task.TaskSearch(this.Application, scopeName, task));
            }
            return tasks;
        }

        public string[] GetTaskNames()
        {
            return Util.ObjectToArrayOfString( this.azRoleAssignment.Tasks);
        }

        /// <summary>
        /// Submits the updates
        /// </summary>
        public void Save()
        {       
            if (azRoleAssignment == null) return;
            this.azRoleAssignment.Name = this.Name;
            this.azRoleAssignment.Description = this.Description;
            this.azRoleAssignment.Submit(0, null);
            AuthorizationSynchronizeManager.SynchronizeManager().UpdateCache();
        }

        /// <summary>
        ///  Abort the updates
        /// </summary>
        public void Abort()
        {
            if (azRoleAssignment == null) return;
            this.azRoleAssignment.Submit((int)tagAZ_PROP_CONSTANTS.AZ_SUBMIT_FLAG_ABORT,
                                         null);
            this.Name = this.azRoleAssignment.Name;
            this.Description = this.azRoleAssignment.Description;
            AuthorizationSynchronizeManager.SynchronizeManager().UpdateCache();
        }

        #region desconstructors

        ~RoleAssignment()
        {

            if (azRoleAssignment != null)
                Marshal.FinalReleaseComObject(azRoleAssignment);
        }

        #endregion      
    }
}
